﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Communication
{
    public class Motor          // 电机类
    {
        private string mID;                     // 电机ID
        private int mAC = 20;                   // 加速度
        private int mDE = 20;                   // 减速度
        private int mVE = 2;                    // 速度
        private int mCurrentPosition = 0;       // 当前位置
        private int mTargetPosition = 200;      // 目标位置

        #region // --------属性-----------------
        public int AC
        {
            get { return mAC; }
            set { mAC = value; }
        }

        public int DE
        {
            get { return mDE; }
            set { mDE = value; }
        }

        public int VE
        {
            get { return mVE; }
            set { mVE = value; }
        }

        public int CurrentPosition
        {
            get { return mCurrentPosition; }
            set { mCurrentPosition = value; }
        }

        public int TargetPosition
        {
            get { return mTargetPosition; }
            set { mTargetPosition = value; }
        }
        #endregion // --------属性-----------------

        #region // 构造函数1: Motor(string id, byte sensorNum)
        public Motor(string id)
        {
            mID = id;
        }

        #endregion // 构造函数1        

        #region // 构造函数2: Motor(string id, byte sensorNum, int goPosition)
        public Motor(string id, int goPosition)
        {
            mID = id;
            mTargetPosition = goPosition;
        }
        #endregion // 构造函数2

        #region // 构造函数3: Motor(string id, int curPosition, int goPosition)
        public Motor(string id, int curPosition, int goPosition)
        {
            mID = id;
            mCurrentPosition = curPosition;
            mTargetPosition = goPosition;
        }
        #endregion // 构造函数3

        #region // 构造函数4: Motor(string id, int ac, int de, int ve, int curPosition, int goPosition)
        public Motor(string id, byte sensorNum, int ac, int de, int ve, int curPosition, int goPosition)
        {
            mID = id;
            mAC = ac;
            mDE = de;
            mVE = ve;
            mCurrentPosition = curPosition;
            mTargetPosition = goPosition;
        }
        #endregion // 构造函数4

        #region // 进给FL，相对移动。参数：进给长度
        public string FeedLength(int distance)
        {
            mTargetPosition = mCurrentPosition + distance;

            string cmd = "", cmdStart = mID, cmdEnd = "\r";     // 下位机为何不用“\n”??
            cmd += cmdStart + "AC" + mAC.ToString() + cmdEnd;
            cmd += cmdStart + "DE" + mDE.ToString() + cmdEnd;
            cmd += cmdStart + "VE" + mVE.ToString() + cmdEnd;
            cmd += cmdStart + "DI" + distance.ToString() + cmdEnd;
            cmd += cmdStart + "FL" + cmdEnd;
            return cmd;
        }
        #endregion // 进给FL，相对移动。参数1：电机编号；参数2：进给长度

        #region // 进给FP，绝对移动。参数：目标位置
        public string FeedPosition(int position)
        {
            mTargetPosition = position;

            string cmd = "", cmdStart = mID, cmdEnd = "\r";     
            cmd += cmdStart + "AC" + mAC.ToString() + cmdEnd;
            cmd += cmdStart + "DE" + mDE.ToString() + cmdEnd;
            cmd += cmdStart + "VE" + mVE.ToString() + cmdEnd;
            cmd += cmdStart + "DI" + position.ToString() + cmdEnd;
            cmd += cmdStart + "FP" + cmdEnd;
            return cmd;
        }
        #endregion // 进给FP，绝对移动。参数1：电机编号；参数2：进给长度

        #region // 限位用FS,回到原点后，不往回动。参数1：方向；参数2：传感器编号；参数3：高/低/升/降
        public string Feed_Sensor(bool direct, int sensorNo, string hlrf)
        {
            string cmd = "", cmdStart = mID, cmdEnd = "\r";
            cmd += cmdStart + "AC" + mAC.ToString() + cmdEnd;
            cmd += cmdStart + "DE" + mDE.ToString() + cmdEnd;
            cmd += cmdStart + "VE" + mVE.ToString() + cmdEnd;

            // 如果电机是顺时针旋转
            if (direct)
            {
                cmd += cmdStart + "DI2000" + cmdEnd;       // 为何用DI2000，不是有传感器编号吗，还要有距离？
            }
            else    // 如果电机是逆时针旋转
            {
                cmd += cmdStart + "DI-2000" + cmdEnd;
            }

            cmd += cmdStart + "FS" + sensorNo.ToString() + hlrf + cmdEnd;
            return cmd;
        }
        #endregion // 移到指定的传感器FS。参数1：电机旋转方向；参数2：传感器编号；参数3：高/低/升/降（与高低电平有关）

        #region // 限位用SH，回到原点后，再往回动一点。参数1：电机旋转方向；参数2：传感器编号；参数3：高/低/升/降
        public string SeekHome(bool isClockWise, byte sensorNo, string hlrf)
        {
            string cmd = "", cmdStart = mID, cmdEnd = "\r";
            cmd += cmdStart + "AC" + mAC.ToString() + cmdEnd;
            cmd += cmdStart + "DE" + mDE.ToString() + cmdEnd;
            cmd += cmdStart + "VE" + mVE.ToString() + cmdEnd;

            // 如果电机是顺时针旋转
            if (isClockWise)
            {
                cmd += cmdStart + "DI2000"  + cmdEnd;       // 为何用DI2000，不是有传感器编号吗，还要有距离？
            }
            else    // 如果电机是逆时针旋转
            {
                cmd += cmdStart + "DI-2000"  + cmdEnd;
            }

            cmd += cmdStart + "SH" + sensorNo.ToString() + hlrf + cmdEnd;
            return cmd;
        }
        #endregion // 回零SH。参数1：方向；参数2：传感器编号；参数3：高/低/升/降（与高低电平有关）

        #region // 移到指定传感器FE，走N个缝停（ednum）。参数1：方向；参数2：脉冲个数；参数3：传感器编号；参数4：电平状态
        public string Feed_Encord(bool isClockWise, int edNum, byte sensorNo, string hlrf)
        {
            string cmd = "", cmdStart = mID, cmdEnd = "\r";
            cmd += cmdStart + "AC" + mAC.ToString() + cmdEnd;
            cmd += cmdStart + "DE" + mDE.ToString() + cmdEnd;
            cmd += cmdStart + "VE" + mVE.ToString() + cmdEnd;
            cmd += cmdStart + "ED" + edNum.ToString() + cmdEnd;   // 有何作用？？
            cmd += cmdStart + "DC90" + cmdEnd;                    // 为何要加DC90？？

            // 如果电机是顺时针旋转
            if (isClockWise)
            {
                cmd += cmdStart + "DI2000" + cmdEnd;
            }
            else    // 如果电机是逆时针旋转
            {
                cmd += cmdStart + "DI-2000" + cmdEnd;
            }

            cmd += cmdStart + "FE" + sensorNo.ToString() + hlrf + cmdEnd;
            return cmd;
        }
        #endregion // 移到指定传感器FE。参数1：方向；参数2：编码器编号；参数3：传感器编号；参数4：电平状态

        #region // 移到指定传感器SE，用于试剂盘找原点。参数1：方向；参数2：传感器编号；参数3：电平状态；参数4：变化距离
        public string Seek_Encord(bool isClockWise, byte sensorNo, string hlrf, int dcLength)
        {
            string cmd = "", cmdStart = mID, cmdEnd = "\r";
            cmd += cmdStart + "AC" + mAC.ToString() + cmdEnd;
            cmd += cmdStart + "DE" + mDE.ToString() + cmdEnd;
            cmd += cmdStart + "VE" + mVE.ToString() + cmdEnd;
           
            // 如果电机是顺时针旋转
            if (isClockWise)
            {
                cmd += cmdStart + "DI2000" + cmdEnd;
            }
            else    // 如果电机是逆时针旋转
            {
                cmd += cmdStart + "DI-2000" + cmdEnd;
            }

            cmd += cmdStart + "DC" + dcLength.ToString() + cmdEnd;
            cmd += cmdStart + "SE" + sensorNo.ToString() + hlrf + cmdEnd;
            return cmd;
        }
        #endregion // 移到指定传感器SE。参数1：方向；参数2：传感器编号；参数3：电平状态；参数4：变化距离

        #region // 设置传感器编号 SS
        public string SetSensor(int Sensor_Num)
        {
            string cmd = "", cmdStart = mID, cmdEnd = "\r";
            cmd += cmdStart + "SS" + Sensor_Num.ToString() + cmdEnd;            
            return cmd;
        }
        #endregion // 设置传感器编号SE

        #region // 紧急停止（下位机工程师专用）
        public string Stop()
        {
            string cmd = "", cmdStart = mID, cmdEnd = "\r";
            cmd += cmdStart + "ST" + cmdEnd;
            return cmd;
        }
        #endregion // 紧急停止（下位机工程师专用）

        // 电机还有其它原子动作，如吸、打，摇晃等
    }
}
